package com.jiyuren.spring.core;


import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.jiyuren.spring.api.OkHttpManager;
import com.jiyuren.spring.bean.TimeMap;
import com.jiyuren.spring.bean.WebSite;
import com.jiyuren.spring.utils.DBConn;
import com.jiyuren.spring.utils.DatabaseSqliteUtil;
import com.jiyuren.spring.utils.DateUtils;
import com.jiyuren.spring.utils.FileUtils;
import com.jiyuren.spring.utils.SpringContextUtil;

import java.io.File;
import java.lang.reflect.Type;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

import javafx.scene.chart.PieChart;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import sun.applet.Main;

/**
 * Created by Administrator on 2017/2/7.
 */
public class MainRun {
    private Map<String, TimeMap> globalMap = new HashMap<String, TimeMap>();
    private Map<String, Long> globalTimes = new HashMap<String, Long>();
    private boolean isRun = false;

    private static volatile MainRun mInstance;

    public static MainRun getInstance() {
        if (mInstance == null) {
            synchronized (MainRun.class) {
                if (null == mInstance) {
                    mInstance = new MainRun();
                }
            }
        }
        return mInstance;
    }


    public static void main(String[] args) {
        try {
            MainRun main = new MainRun();
            main.start();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public List<WebSite> getList() {
        DatabaseSqliteUtil db = SpringContextUtil.getBean("databaseUtil");
        List<WebSite> list = db.getList(db.getConnection());
        return list;
    }

    public void setRun(boolean run) {
        isRun = run;
    }

    public void startWhile() throws ExecutionException, InterruptedException {
        while (isRun) {
            execute(getList());
            System.out.println("回收内存>>>>>>>>>>>>>>>>>>>>>>>>>");
            System.gc();
        }
    }

    public void start() throws ExecutionException, InterruptedException {
//        while (true) {
        execute(getList());
        System.out.println("回收内存>>>>>>>>>>>>>>>>>>>>>>>>>");
        System.gc();
//        }
    }

    public void execute(List<WebSite> list) throws ExecutionException, InterruptedException {
//        long start = System.currentTimeMillis();
        List<FutureTask<String>> futureTasks = new ArrayList<FutureTask<String>>();
        int size = list.size();
        System.out.println("size = " + size);
        ExecutorService executorService = Executors.newFixedThreadPool(size);
        OkHttpClient client = OkHttpManager.getInstance().getClient();
        for (int j = 0; j < size; j++) {
            WebSite item = list.get(j);
            FutureTask<String> task = new FutureTask<String>(mCallable(item, client));
            futureTasks.add(task);
            executorService.submit(task);
        }
//        for (FutureTask<String> task : futureTasks) {
//            task.get();
//        }
        System.out.println("shutdown------------------------------------------");
        executorService.shutdown();
//        long end = System.currentTimeMillis();
//        System.out.println("线程池的任务全部完成 main线程关闭，进行线程的清理");
//        System.out.println("使用时间：" + (end - start) + "ms");
    }


    private Callable<String> mCallable(final WebSite item, final OkHttpClient client) {
        return new Callable<String>() {
            public String call() throws Exception {
                long mStartTime = System.currentTimeMillis();

                String url = item.getUrl();
                Request request = new Request.Builder()
                        .url(url)
                        .get()
                        .build();


                int isRun = item.getIs_run();
                if (isRun == 0) {
                    return "";
                }
                String accessTime = item.getAccess_time();
                if (!accessTime.equals("1")) {
                    String startEndTime[] = getStartEndTime(accessTime);
                    String startTime = startEndTime[0];
                    String endTime = startEndTime[1];
                    boolean isInAccessTime = isInAccessTime(str2longTime(startTime), str2longTime(endTime));
                    if (!isInAccessTime) {
                        return "";
                    }
                }
                String id = item.getId() + "";
                String title = item.getTitle_name();
                int timeInterval = item.getAccess_time_interval() * 1000;
//                Thread.sleep(timeInterval);
                System.out.println("沉睡" + timeInterval + "url = " + item.getUrl());

                if (!globalMap.isEmpty() && globalMap.containsKey(id)) {
                    long startTime = globalMap.get(id).getStartTime();
                    long endTime = globalMap.get(id).getEndTime();
                    long accessTimeInterval = endTime - startTime;

                    mStartTime = startTime;
                    if (accessTimeInterval >= timeInterval) {
                        System.out.println("执行+++++++++++++++++++++++++++++++++++++++++++++++");
                        mStartTime = System.currentTimeMillis();
                    } else {
                        System.out.println("不执行<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
                        globalMap.put(id, new TimeMap(mStartTime, System.currentTimeMillis()));
                        return "";
                    }
                }
                globalMap.put(id, new TimeMap(mStartTime, System.currentTimeMillis()));
                Response response = client.newCall(request).execute();
                long count = 1;
                if (!globalTimes.isEmpty() && globalTimes.containsKey(id)) {
                    count = globalTimes.get(id);
                    count += 1;
                    globalTimes.put(id, count);
                } else {
                    globalTimes.put(id, count);
                }
                System.out.println(globalTimes.toString());
                if (null != mGetAccessTimesListener) {
                    mGetAccessTimesListener.getAccessTimes(id, String.valueOf(count));
                }
                String result = response.body().string();
                try {
//                    Type type = new TypeToken<List<String>>(){}.getType();
                    Gson gson = new Gson();
                    ParentUrl purl = gson.fromJson(result, ParentUrl.class);
                    List<String> list = purl.getUrllist();
                    if (!list.isEmpty()) {
                        requestChild(id, list);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

                String prefix = "url:" + url + "\ttitle:" + title + "\ttime" + DateUtils.getCurrTimeMs() + "\n";
                createFile(id, title, prefix + result);
                return result;
            }
        };
    }

    public void requestChild(String id, List<String> list) {
        System.out.println("requestChild");
        if (null != mStopChildListener) {
            boolean isStop = mStopChildListener.isStopChild();
            System.out.println("isStop = " + isStop);
                int size = list.size();
                ExecutorService executorService = Executors.newFixedThreadPool(size);
                OkHttpClient client = OkHttpManager.getInstance().getClient();
                for (int j = 0; j < size; j++) {
                    String item = list.get(j);
                    FutureTask<String> task = new FutureTask<String>(mChildCallable(id, item, client));
                    executorService.submit(task);
                }
                System.out.println("shutdown child ------------------------------------------");
                executorService.shutdown();
                System.out.println("回收child内存>>>>>>-----------------------------");
                System.gc();
        }
    }

    private Callable<String> mChildCallable(final String id, final String url, final OkHttpClient client) {
        return new Callable<String>() {
            public String call() throws Exception {
                Request request = new Request.Builder()
                        .url(url)
                        .get()
                        .build();

                Response response = client.newCall(request).execute();
                String result = response.body().string();
                System.out.println(result);
                try {
//                    Type type = new TypeToken<List<String>>(){}.getType();
                    Gson gson = new Gson();
                    ParentUrl purl = gson.fromJson(result, ParentUrl.class);
                    List<String> list = purl.getUrllist();
                    if (!list.isEmpty()) {
                        Thread.sleep(1000);
                        requestChild(id, list);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                String title = "child";
                String prefix = "url:" + url + "\ttitle:" + title + "\ttime" + DateUtils.getCurrTimeMs() + "\n";
                System.out.println("写child文件start...");
                createFile("child_" + id, title, prefix + result);
                System.out.println("写child文件end...");
                return result;
            }
        };
    }

    public String filePath = "D:/";

    public void createFile(String id, String title, String data) {
        System.out.println("写文件start...");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy_MM_dd_HH");
        Calendar calendar = Calendar.getInstance();
        Date date = calendar.getTime();
        String dateName = sdf.format(date);
        String fileName = "log_" + dateName + ".txt";
        File file = new File(filePath + "log/" + id + "_" + title + "/" + fileName);
        File parentFile = file.getParentFile();
        if (!parentFile.exists()) {
            parentFile.mkdirs();
        }
        try {
            file.createNewFile();
            FileUtils.writeTextFile(file, data);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("写文件end...");
    }

    public long str2longTime(String time) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String currDate = dateFormat.format(calendar.getTime());
        try {
            Date date = sdf.parse(currDate + " " + time);
            long dateTime = date.getTime();
            return dateTime;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return 0;
    }

    private boolean isInAccessTime(long startTime, long endTime) {
        long nowTime = System.currentTimeMillis();
        System.out.println("nowTime:" + nowTime + " startTime=" + startTime + " endTime=" + endTime);
        if (nowTime > startTime && nowTime < endTime) {
            System.out.println("在指定时间内");
            return true;
        }
        System.out.println("不在指定时间内");
        return false;
    }

    private String[] getStartEndTime(String accessTime) {
        if (accessTime.contains("-")) {
            return accessTime.split("-");
        }
        return null;
    }

    public StopChildListener mStopChildListener;

    public void setStopChildListener(StopChildListener l) {
        mStopChildListener = l;
    }

    public GetAccessTimesListener mGetAccessTimesListener;

    public void setGetAccessTimesListener(GetAccessTimesListener l) {
        mGetAccessTimesListener = l;
    }

    public interface GetAccessTimesListener {
        void getAccessTimes(String id, String times);
    }

    public interface StopChildListener {
        boolean isStopChild();
    }
}
